<?php
/**
 * winbinder 패키지 
 * 
 * 
 * @package php.ui.winbinder
 */

/**
 * WBObject, 최상위 클래스 
 *
 * @package php.ui.winbinder
 */
class WBObject extends PObject implements ArrayAccess { 
	private $_defaultEvent = array();
	private $_userEvent = array();
	private $_options = array();

	/**
	 * WBObject 생성자 
	 *
	 * 내부적으로 id 속성이 지정되어 있지 않으면 id를 자동으로 생성해서 등록한다. 
	 *
	 * @param array $options WBObject 에 설정될 옵션 리스트 
	 */
	public function __construct($options = array()) { 

		// 아이디 설정 
		$options['id'] = (isset($options['id'])) ? $options['id'] : WBApplication::getIdCount() ;
		WBApplication::setObject($options['id'], $this);

		// 상수 설정 
		if ($options['name']) { 
			WBApplication::setName($options['name'], $options['id']);
		}

		// 속성 설정 
		$this->setOptionList($options);

		// 이벤트 설정 함수 
		$this->initEvent();
	}

	public function __destruct() {
		//unset($this->_defaultEvent);
		//unset($this->_userEvent);
		//unset($this->_options);
	} 

	/**
	 * 
	 * set event sample
	 * 
	 * event => array('click' => 'callback')
	 * 
	 * event => array('click' => array('callback', 'callback2')
	 * 
	 * @return unknown_type
	 */
	protected function initEvent() { 

		// 이벤트 설정이 있을 때
		if (isset($this->event)) { 
			foreach ($this->getOption('event') as $event => $callback) {

				if (is_callable($callback)) { 
					$this->on($event, $callback);
				} else if (is_array($callback)) { 
					foreach ($callback as $event2 => $callback2) { 
						$this->on($event2, $callback2);
					}
				} else { 
					$this->on($event, $callback);
				}
			}
		}
	}

	/**
	 * option 설정 
	 *
	 * @param string $key option key 
	 * @param mixed $value option value 
	 */
	public function setOption($key, $value) { 
		$this->_options[$key] = $value;
	}

	/**
	 * options 설정 
	 *
	 * @param array options 
	 */
	public function setOptionList($options = array()) {
		$this->_options = array_merge($this->_options, $options);
	}

	/**
	 * $key 에 맞는 값 가져오기 
	 *
	 * @param string $key option key 
	 * @return mixed option value 
	 */
	public function getOption($key) { 
		return $this->_options[$key];
	}

	/**
	 * option list 
	 *
	 * @return array 
	 */
	public function getOptionList() { 
		return $this->_options;
	}

	/**
	 * 기본 이벤트에 해당하는 callback 함수 설정 
	 *
	 * @param string $event 이벤트 이름 
	 * @param string|array $function callback 함수 
	 */
	public function setEvent($event, $function) { 
		$this->_defaultEvent[$event] = $function;
	}

	/**
	 * 사용자 이벤트 추가 
	 * 
	 * @param string $event 이벤트 이름 
	 * @param string|array $function callback 함수 
	 */
	public function addEvent($event, $function) { 
		$this->_userEvent[$event][] = $function;
	}

	/**
	 * addEvent() 와 같음
	 *
	 * @param string $event 이벤트 이름 
	 * @param string|array $function callback 함수 
	 */
	public function on($event, $function) { 
		$this->addEvent($event, $function);
	}
	
	public function removeEvent($event, $function) {
		$e = $this->_userEvent[$event];
		 
		$index = array_search($function, $e) ;
		
		unset($this->_userEvent[$event][$index]);
	}

	/**
	 * option value 설정하기 
	 *
	 * <code>$obj->class = AppWindow;</code>
	 *
	 * @param string $key option key 
	 * @param mixed $value option value 
	 */
	public function __set($key, $value) { 
		$method= "set".ucwords($key);
		
		if (method_exists($this, $method)) { 		
			$this->$method($value);
		}
	}

	/**
	 * $key 에 맞는 값 가져오기 
	 *
	 * <code>echo $obj->class;</code>
	 *
	 * @param string $key option key 
	 * @return mixed option value 
	 */
	public function __get($key) { 
		$method= "get".ucwords($key);
		
		if (method_exists($this, $method)) { 
			return $this->$method();
		}
	}


	/**
	 * 옵션 설정 여부 체크 
	 *
	 * <code>
	 * if (isset($obj->class)) { 
	 *    echo 'class 옵션이 설정되어 있음';
	 * }
	 * </code>
	 * 
	 * @param string $key option key 
	 */
	public function __isset($key) { 
		return isset($this->_options[$key]);
	}

	/**
	 * option 메모리 해제 
	 *
	 * @param string $key option key 
	 */
	public function __unset($key) { 
		unset($this->_options[$key]);
	}
	
	/**
	 * 이벤트 실행 
	 * 
	 * <code> $com->fireEvent('click', $eventObject);</code>
	 *
	 */
	public function fireEvent($event, $eventObject = null) { 

		// 기본 이벤트
		if (array_key_exists($event, $this->_defaultEvent)) {
			$defaultCallback = array($this, $this->_defaultEvent[$event]);
			if (is_callable($defaultCallback)){
				call_user_func($defaultCallback, $eventObject);	
			}
		}
		
		// 사용자 이벤트 
		if (array_key_exists($event, $this->_userEvent)) {

			foreach ($this->_userEvent[$event] as $func) {
				if (is_callable($func)) { 
					call_user_func($func, $eventObject);
				}
			}
		}
	}

	/** 
	 * 이벤트 실행 출발점 
	 * 각 타입에 맞는 이벤트 재지정 
	 *
	 */
	protected function fire($eo) { 
		
	}
	

	/**
	 * 속성 존재여부 확인 
	 * 
	 * @return boolean
	 */
	public function offsetExists($name) {
		return isset($this->_options[$name]);
	}

	/**
	 * 속성 값 얻어오기 
	 * 
	 * @return mixed
	 */
	public function offsetGet($name) {
		return $this->getOption($name);
	}

	/**
	 * 속성 값 설정
	 */
	public function offsetSet($name, $value) {
		$this->setOption($name, $value);
	}

	/**
	 *  속성 값 비우기 
	 */
	public function offsetUnset($name) {
		unset($this->_options[$name]);
	}

	
}

?>